iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0
Software Development

從 Vibe Coding 到可維護專案:用 Hermes Agent 重讀 RoomRush Android 專題系列 第 21 篇

Day 21 | 管理者要修改一間教室,首先要怎麼找到它?(上)

  • 分享至 

  • xImage
  •  

前言:教室這麼多,管理者點進「教室細項設定」後,App 怎麼知道他想修改哪一間?

上一篇我們說明了 RoomRush 的第一條分支--「課表管理」;今天的第二條分支是「教室詳細設定」。

DetailChooseActivity.kt 這檔案是顯示教室清單,讓管理者點選其中一間教室時,並傳遞教室名稱傳給下一頁,而 ClassroomAdapter.kt 的用意是把教室清單變成 RecyclerView Adapter,並讓管理者可以點選。


一開始我認為

一開始在設計這個頁面時,我曾直覺認為既然核心就是列表呈現,把邏輯與 RecyclerView.Adapter 全寫在同一個檔案最省事,甚至一度想把 DetailChooseActivity.kt 與 ClassroomAdapter.kt 混在一起寫。

但這正好呼應了前面一再強調的職責分離:

  • ClassroomAdapter 專注於「View 的渲染與資料綁定」:只管每一列 UI 怎麼畫。
  • DetailChooseActivity 專注於「流程控制與使用者互動」:只管點擊後的邏輯跳轉與事件處理。

這樣的拆分大幅降低了單一檔案的複雜度。未來若要修改列表排版,或是微調教室選取後的行為,都能各自獨立維護。

UI 畫面 操作流程
UI 畫面 操作流程

實際讀完後,DetailChooseActivity.kt 和 ClassroomAdapter.kt 負責什麼

和 Hermes Agent 一起重讀教室細項頁面和其 Adapter 後,這兩個檔案扮演的是「挑選教室」的入口關卡:讓管理者從清單中點選特定教室,並將教室代號(如 SF304)傳遞到下一頁的管理畫面。

兩者的分工非常純粹:DetailChooseActivity.kt 負責「抓取資料與協調」, ClassroomAdapter.kt 負責「繪製畫面與觸發跳頁」。

1. DetailChooseActivity.kt:資料中繼與畫面監聽

角色定位:只負責觀察資料與組裝介面。

核心實作:
1.薄 ViewModel(Thin ViewModel): 透過 AppContainer 注入 Repository,將全校課表轉為 LiveData 供畫面觀察。
2.資料加工後分發: 監聽到資料庫更新時,提取出不重複的教室名稱並排序,整包交給 Adapter:

viewModel.allClassrooms.observe(this) { schedules ->
    val classroomNames = schedules.map { it.classroom }.sorted()
    adapter.updateData(classroomNames)
}

可維護性觀察: 檔案名稱為 DetailChooseActivity.kt,但內部 Class 名稱卻是 ClassroomChooseManageActivity,是早期開發遺留下的命名不一致。

2. ClassroomAdapter.kt:文字渲染與跳頁事件

角色定位:單純接收 List<String>(教室名稱清單),將字串轉化為單列 Item。

核心實作:

  1. 單一 TextView 綁定: 每個 Item 只呈現純文字(如教室編號)。
  2. 直接在 Adapter 觸發導頁: 點擊任一列時,直接從 Adapter 發送 Intent 帶著教室名稱跳轉至下一頁:
holder.itemView.setOnClickListener {
    val intent = Intent(it.context, ClassroomManageActivity::class.java).apply {
        putExtra("CLASSROOM_NAME", classroom)
    }
    it.context.startActivity(intent)
}

可維護性觀察:

  1. 列表更新目前使用全量重繪的 notifyDataSetChanged(),未來若資料量擴大,可導入 ListAdapter 搭配 DiffUtil。
  2. 點擊跳轉直接寫死在 Adapter 內部,造成 Adapter 與目標 Activity 強耦合;更理想的架構是透過 Lambda 將點擊事件拋回給 Activity 統一調度。

它接在哪一條流程上

完整的教室選擇流程(DetailChooseActivity.kt)

ManagerActivity
「點擊教室細項設定」
        ↓
ClassroomChooseManageActivity
        ↓
ViewModel
「取得所有教室課表」
        ↓
Activity
「整理成教室名稱清單」
        ↓
ClassroomAdapter
「顯示教室列表」
        ↓
管理者選擇一間教室
        ↓
傳遞教室名稱 CLASSROOM_NAME
        ↓
ClassroomManageActivity
「進入教室設定頁」

ClassroomAdapter.kt 內部流程

教室名稱清單
        ↓
adapter.updateData()
「更新 Adapter 的資料」
        ↓
ClassroomAdapter
「顯示教室列表」
        ↓
管理者點選教室
        ↓
回傳所選教室名稱

ClassroomAdapter 負責將教室名稱清單顯示在列表中。
當管理者點選某間教室時,Adapter 會透過點擊事件將選取的教室名稱傳回 Activity,再由 Activity 使用 Intent 將 CLASSROOM_NAME 傳給 ClassroomManageActivity。


Hermes Agent 幫我檢查出的重點

DetailChooseActivity是教室詳細設定流程中的教室選擇頁。實際的 class 名稱是 ClassroomChooseManageActivity ,layout 是 detail_choose.xml。

  • 本頁從 ManagerActivity 的「教室細項設定」入口進入,透過 ClassroomChooseManageViewModel 從 Repository 取得所有課表資料。
  • Activity observe allClassrooms 後,將 List<ClassroomSchedule> 轉成排序後的 List<String> 教室名稱清單,交給 ClassroomAdapter 顯示在 RecyclerView。
  • 當管理者點選某一間教室時,ClassroomAdapter 會建立前往 ClassroomManageActivity 的 Intent,並用 CLASSROOM_NAME 傳出被點選的教室名稱。

這頁本身不修改資料庫,而是負責選擇要設定哪一間教室。

ClassroomAdapter 是教室詳細設定流程中的 RecyclerView Adapter。

  • 它接收 List<String> 教室名稱清單,使用 item_classroom.xml 作為每一列的 layout。
  • onCreateViewHolder() 會建立 item view,onBindViewHolder() 會把目前位置的教室名稱綁定到 classroom_name 這個 TextView,並設定點擊事件。
  • 當管理者點擊某一間教室時,Adapter 會建立前往 ClassroomManageActivity 的 Intent,並用 putExtra("CLASSROOM_NAME", classroom) 傳出教室名稱。
  • updateData() 則會用新教室清單取代舊資料,並呼叫 notifyDataSetChanged() 讓整個列表重新刷新。

這個檔案帶出的維護觀察

  1. 檔案名與類別命名不一致:檔案名稱是 DetailChooseActivity.kt,裡面的 class 卻是 ClassroomChooseManageActivity。Kotlin 語法雖允許檔名與 class 不同名,但搜尋類別時很容易找不到檔案,在專案架構導覽上增加不必要的認知成本。
  2. Adapter 與跳轉邏輯耦合:Adapter 內部直接負責啟動下一個 Activity(startActivity),越權處理了頁面導航的職責。理想做法應利用 Lambda 或 Callback 將點擊事件拋回給 Activity,由 Activity 統一控制畫面流向,讓 Adapter 專注於資料綁定與展示。
  3. 全量刷新機制粗劣:資料更新時直接呼叫 notifyDataSetChanged(),會迫使整個 RecyclerView 重繪所有 item,既浪費效能也缺少流暢的過渡動畫。未來可遷移至 ListAdapter 搭配 DiffUtil,透過差量比對達成精準的局部刷新。
  4. Item 版面資訊單薄:目前的 item 佈局只顯示單純的教室名稱。後續可擴充顯示「教室類型」、「是否可飲食」以及「所在樓層」等標籤,並在頁面頂端補上關鍵字搜尋或屬性篩選機制,提升管理者的查找效率。

小結

在管理者功能裡,教室細項設定不是直接進入修改頁,而是先經過一個教室選擇頁。
這個頁面的 class 叫 ClassroomChooseManageActivity,但實際檔案是 DetailChooseActivity.kt,layout 是 detail_choose.xml。這種命名不一致不會讓程式不能跑,但讀專案時很容易迷路,也是一個可維護性觀察。

這頁的流程很單純:它從 Repository 取得所有教室資料,轉成教室名稱清單,交給 RecyclerView 顯示。管理者點選其中一間教室後,Adapter 會把教室名稱用 CLASSROOM_NAME 傳給 ClassroomManageActivity。所以這頁比較像「選擇入口」,真正修改教室詳細資料的邏輯要到下一個頁面才會出現。

ClassroomAdapter 是一個很短的檔案,但它剛好連接了教室選擇頁和教室詳細設定頁。
前一頁 ClassroomChooseManageActivity 只負責取得所有教室名稱並交給 Adapter,Adapter 則把這些名稱顯示成 RecyclerView 的列表項目。

比較值得注意的是,這個 Adapter 不只是顯示資料,它也直接處理點擊跳頁。當使用者點擊某一間教室時,Adapter 會建立 Intent,前往 ClassroomManageActivity,並用 CLASSROOM_NAME 傳出教室名稱。這樣寫可以讓程式短一點,但 Adapter 會知道下一頁是誰,和頁面跳轉產生耦合。若未來要改善,可以改成 Adapter 只回傳點擊事件,讓 Activity 決定跳轉邏輯。

各用一句話總結這兩個檔案:

DetailChooseActivity 顯示所有教室清單,讓管理者點選一間教室,並把 CLASSROOM_NAME 傳給 DetailSetupActivity。

ClassroomAdapter 把教室名稱清單顯示成 RecyclerView 列表,並在點擊某一間教室時,把 CLASSROOM_NAME 傳給 DetailSetupActivity。


下一篇預告:選到教室之後,資料怎麼被查出來並修改?(下)

到這裡,我們完成了「教室清單選取」的流程,讓 App 能夠精確鎖定管理者想異動的目標教室。然而,光是選定「哪一間」還不夠,真正的核心在於 如何修改教室的細項設定。

下一篇,我們將正式走進「教室細項設定」的最後一哩路--解密 DetailSetupActivity.kt 。看看畫面如何接收傳遞過來的 CLASSROOM_NAME 參數,最終完成教室類型(Classroom Type)的更新與存檔。


上一篇
Day 20 | 管理者選擇「是 / 否」有課之後,課表資料怎麼被改掉?
下一篇
Day 22 | 選到教室之後,資料怎麼被查出來並修改?(下)
系列文
從 Vibe Coding 到可維護專案:用 Hermes Agent 重讀 RoomRush Android 專題 共 23 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言